Micron Document
NexusPi Git Node

Node / mirrors / RTNode-HeltecV4 / files / FileSystem.cpp

Displaying Raw • Download

FileSystem.cpp HEAD (ee519cc2) Text, 14.89 KB

Tff7b72#Tff7b72include T8b949e"FileSystem.h"
Tff7b72#Tff7b72include T8b949e"FileStream.h"
Tff7b72#Tff7b72include T8b949e"FileSystemType.h"

Tff7b72#Tff7b72ifdef HAS_RNS

Tff7b72#Tff7b72include T8b949e<Log.h>
Tff7b72#Tff7b72include T8b949e<sys/stat.h>

T8b949e// Safe existence check that uses stat() directly instead of FS.exists().
T8b949e// FS.exists() on LittleFS calls LittleFSImpl::exists() which internally
T8b949e// calls VFSImpl::open(path, "r") — and that triggers the noisy
T8b949e// "does not exist, no permits for creation" VFS error (vfs_api.cpp:105)
T8b949e// whenever the file/directory is absent.
Tff7b72static Tffa657bool Td2a8ffpath_existsTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3pathTb4b4b4) Tb4b4b4{
Tff7b72struct T56d364stat Te6edf3stTb4b4b4;
Tff7b72return Tb4b4b4(Tff7b72:Tff7b72:Te6edf3statTb4b4b4(Te6edf3pathTb4b4b4, Tff7b72&Te6edf3stTb4b4b4) Tff7b72=Tff7b72= T79c0ff0Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72#Tff7b72if FS_TYPE == FS_TYPE_INTERNALFS

Tff7b72inline Tffa657int Td2a8ff_countLfsBlockTb4b4b4(Tffa657void Tff7b72*Te6edf3pTb4b4b4, Te6edf3lfs_block_t Te6edf3blockTb4b4b4) Tb4b4b4{
Te6edf3lfs_size_t Tff7b72*Te6edf3size Tff7b72= Tb4b4b4(Te6edf3lfs_size_tTff7b72*Tb4b4b4) Te6edf3pTb4b4b4;
Tff7b72*Te6edf3size Tff7b72+Tff7b72= T79c0ff1Tb4b4b4;
Tff7b72return T79c0ff0Tb4b4b4;
Tb4b4b4}

Te6edf3lfs_ssize_t Td2a8ffusedBlocksTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3lfs_size_t Te6edf3size Tff7b72= T79c0ff0Tb4b4b4;
Te6edf3lfs_traverseTb4b4b4(Te6edf3FSTb4b4b4.Te6edf3_getFSTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3_countLfsBlockTb4b4b4, Tff7b72&Te6edf3sizeTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3sizeTb4b4b4;
Tb4b4b4}

Tffa657size_t Td2a8ffusedBytesTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3lfs_configTff7b72* Te6edf3config Tff7b72= Te6edf3FSTb4b4b4.Te6edf3_getFSTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3cfgTb4b4b4;
Tff7b72const Tffa657size_t Te6edf3usedBlockCount Tff7b72= Te6edf3usedBlocksTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3configTff7b72-Tff7b72>Te6edf3block_size Tff7b72* Te6edf3usedBlockCountTb4b4b4;
Tb4b4b4}

Tffa657size_t Td2a8fftotalBytesTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3lfs_configTff7b72* Te6edf3config Tff7b72= Te6edf3FSTb4b4b4.Te6edf3_getFSTb4b4b4(Tb4b4b4)Tff7b72-Tff7b72>Te6edf3cfgTb4b4b4;
Tff7b72return Te6edf3configTff7b72-Tff7b72>Te6edf3block_size Tff7b72* Te6edf3configTff7b72-Tff7b72>Te6edf3block_countTb4b4b4;
Tb4b4b4}

Tff7b72#Tff7b72elif FS_TYPE == FS_TYPE_FLASHFS

Te6edf3Adafruit_FlashTransport_SPI Td2a8ffg_flashTransportTb4b4b4(Te6edf3SSTb4b4b4, Te6edf3SPITb4b4b4)Tb4b4b4;

T8b949e//Flash definition structure for GD25Q16C Flash (RAK15001)
Te6edf3Cached_SPIFlash Td2a8ffg_flashTb4b4b4(Tff7b72&Te6edf3g_flashTransportTb4b4b4)Tb4b4b4;
Te6edf3SPIFlash_Device_t Te6edf3g_RAK15001 Tb4b4b4{
Tb4b4b4.Te6edf3total_size Tff7b72= Tb4b4b4(T79c0ff1UL Tff7b72<Tff7b72< T79c0ff21Tb4b4b4)Tb4b4b4,
Tb4b4b4.Te6edf3start_up_time_us Tff7b72= T79c0ff5000Tb4b4b4,
Tb4b4b4.Te6edf3manufacturer_id Tff7b72= T79c0ff0xc8Tb4b4b4,
Tb4b4b4.Te6edf3memory_type Tff7b72= T79c0ff0x40Tb4b4b4,
Tb4b4b4.Te6edf3capacity Tff7b72= T79c0ff0x15Tb4b4b4,
Tb4b4b4.Te6edf3max_clock_speed_mhz Tff7b72= T79c0ff15Tb4b4b4,
Tb4b4b4.Te6edf3quad_enable_bit_mask Tff7b72= T79c0ff0x00Tb4b4b4,
Tb4b4b4.Te6edf3has_sector_protection Tff7b72= Tffa657falseTb4b4b4,
Tb4b4b4.Te6edf3supports_fast_read Tff7b72= Tffa657trueTb4b4b4,
Tb4b4b4.Te6edf3supports_qspi Tff7b72= Tffa657falseTb4b4b4,
Tb4b4b4.Te6edf3supports_qspi_writes Tff7b72= Tffa657falseTb4b4b4,
Tb4b4b4.Te6edf3write_status_register_split Tff7b72= Tffa657falseTb4b4b4,
Tb4b4b4.Te6edf3single_status_byte Tff7b72= Tffa657trueTb4b4b4,
Tb4b4b4}Tb4b4b4;

Tff7b72#Tff7b72endif


Tffa657bool Td2a8ffFileSystem::initTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffInitializing filesystem...Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72#Tff7b72if FS_TYPE == FS_TYPE_SPIFFS
T8b949e// Initialize SPIFFS
Te6edf3INFOTb4b4b4(Ta5d6ff"Ta5d6ffSPIFFS mounting filesystemTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3SPIFFSTb4b4b4.Te6edf3beginTb4b4b4(Tffa657trueTb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3ERRORTb4b4b4(Ta5d6ff"Ta5d6ffSPIFFS filesystem mount failedTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}
Te6edf3INFOTb4b4b4(Ta5d6ff"Ta5d6ffSPIFFS filesystem is readyTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif FS_TYPE == FS_TYPE_LITTLEFS
T8b949e// Initialize LittleFS
Te6edf3INFOTb4b4b4(Ta5d6ff"Ta5d6ffLittleFS mounting filesystemTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3LittleFSTb4b4b4.Te6edf3beginTb4b4b4(Tffa657trueTb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3ERRORTb4b4b4(Ta5d6ff"Ta5d6ffLittleFS filesystem mount failedTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}
Te6edf3DEBUGTb4b4b4(Ta5d6ff"Ta5d6ffLittleFS filesystem is readyTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif FS_TYPE == FS_TYPE_INTERNALFS
T8b949e// Initialize InternalFileSystem
Te6edf3INFOTb4b4b4(Ta5d6ff"Ta5d6ffInternalFS mounting filesystemTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3InternalFSTb4b4b4.Te6edf3beginTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3ERRORTb4b4b4(Ta5d6ff"Ta5d6ffInternalFS filesystem mount failedTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}
Te6edf3INFOTb4b4b4(Ta5d6ff"Ta5d6ffInternalFS filesystem is readyTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72elif FS_TYPE == FS_TYPE_FLASHFS
T8b949e// Initialize FlashFileSystem
Te6edf3INFOTb4b4b4(Ta5d6ff"Ta5d6ffFlashFS mounting filesystemTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3g_flashTb4b4b4.Te6edf3beginTb4b4b4(Tff7b72&Te6edf3g_RAK15001Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3ERRORTb4b4b4(Ta5d6ff"Ta5d6ffFlashFS failed to initializeTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3FlashFSTb4b4b4.Te6edf3beginTb4b4b4(Tff7b72&Te6edf3g_flashTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3ERRORTb4b4b4(Ta5d6ff"Ta5d6ffFlashFS filesystem mount failedTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}
Tff7b72#Tff7b72endif
T8b949e// Ensure filesystem is writable and reformat if not
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Bytes Te6edf3testTb4b4b4(Ta5d6ff"Ta5d6fftestTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3write_fileTb4b4b4(Ta5d6ff"Ta5d6ff/testTa5d6ff"Tb4b4b4, Te6edf3testTb4b4b4) Tff7b72< T79c0ff4Tb4b4b4) Tb4b4b4{
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffFailed to write test file, filesystem is being reformatted...Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_CRITICALTb4b4b4)Tb4b4b4;
T8b949e//FS.format();
Te6edf3reformatTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72else Tb4b4b4{
Te6edf3remove_fileTb4b4b4(Ta5d6ff"Ta5d6ff/testTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e// Ensure cache directory exists before Transport starts.
T8b949e// If this fails, packet caching will be unavailable but the
T8b949e// node will still operate (paths just won't survive reboots).
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3directory_existsTb4b4b4(Ta5d6ff"Ta5d6ff/cacheTa5d6ff"Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3create_directoryTb4b4b4(Ta5d6ff"Ta5d6ff/cacheTa5d6ff"Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3HEADTb4b4b4(Ta5d6ff"Ta5d6ffFailed to create /cache directory — packet cache will be unavailableTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3LOG_CRITICALTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}
Tff7b72catch Tb4b4b4(Te6edf3stdTff7b72:Tff7b72:Te6edf3exceptionTff7b72& Te6edf3eTb4b4b4) Tb4b4b4{
T8b949e//ERROR("FileSystem init Exception: " + std::string(e.what()));
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6ffFinished initializingTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72return Tffa657trueTb4b4b4;
Tb4b4b4}

Tffa657bool Td2a8ffFileSystem::formatTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3INFOTb4b4b4(Ta5d6ff"Ta5d6ffFormatting filesystem...Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3FSTb4b4b4.Te6edf3formatTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3ERRORTb4b4b4(Ta5d6ff"Ta5d6ffFormat failed!Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}
Tff7b72return Tffa657trueTb4b4b4;
Tb4b4b4}
Tff7b72catch Tb4b4b4(Te6edf3stdTff7b72:Tff7b72:Te6edf3exceptionTff7b72& Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3ERRORTb4b4b4(Ta5d6ff"Ta5d6ffFileSystem reformat Exception: Ta5d6ff" Tff7b72+ Te6edf3stdTff7b72:Tff7b72:Te6edf3stringTb4b4b4(Te6edf3eTb4b4b4.Te6edf3whatTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}

Tffa657bool Td2a8ffFileSystem::reformatTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3INFOTb4b4b4(Ta5d6ff"Ta5d6ffReformatting filesystem...Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Bytes Te6edf3eepromTb4b4b4;
Te6edf3read_fileTb4b4b4(Ta5d6ff"Ta5d6ff/eepromTa5d6ff"Tb4b4b4, Te6edf3eepromTb4b4b4)Tb4b4b4;
Te6edf3RNSTff7b72:Tff7b72:Te6edf3Bytes Te6edf3transport_identityTb4b4b4;
Te6edf3read_fileTb4b4b4(Ta5d6ff"Ta5d6ff/transport_identityTa5d6ff"Tb4b4b4, Te6edf3transport_identityTb4b4b4)Tb4b4b4;
T8b949e//RNS::Bytes time_offset;
T8b949e//read_file("/time_offset", time_offset);
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3FSTb4b4b4.Te6edf3formatTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3ERRORTb4b4b4(Ta5d6ff"Ta5d6ffFormat failed!Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3eepromTb4b4b4) Tb4b4b4{
Te6edf3write_fileTb4b4b4(Ta5d6ff"Ta5d6ff/eepromTa5d6ff"Tb4b4b4, Te6edf3eepromTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3transport_identityTb4b4b4) Tb4b4b4{
Te6edf3write_fileTb4b4b4(Ta5d6ff"Ta5d6ff/transport_identityTa5d6ff"Tb4b4b4, Te6edf3transport_identityTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e//if (time_offset) {
T8b949e// write_file("/time_offset", time_offset);
T8b949e//}
Tff7b72return Tffa657trueTb4b4b4;
Tb4b4b4}
Tff7b72catch Tb4b4b4(Te6edf3stdTff7b72:Tff7b72:Te6edf3exceptionTff7b72& Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3ERRORTb4b4b4(Ta5d6ff"Ta5d6ffFileSystem reformat Exception: Ta5d6ff" Tff7b72+ Te6edf3stdTff7b72:Tff7b72:Te6edf3stringTb4b4b4(Te6edf3eTb4b4b4.Te6edf3whatTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}

Tff7b72#Tff7b72ifndef NDEBUG

Tffa657void Te6edf3FileSystemTff7b72:Tff7b72:Te6edf3listDirTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3dirTb4b4b4, Tff7b72const Tffa657charTff7b72* Te6edf3prefix T8b949e/*= ""*/Tb4b4b4) Tb4b4b4{
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Te6edf3prefixTb4b4b4)Tb4b4b4;
Te6edf3stdTff7b72:Tff7b72:Te6edf3string Td2a8fffull_dirTb4b4b4(Te6edf3dirTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3full_dirTb4b4b4.Te6edf3compareTb4b4b4(Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4) Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3full_dir Tff7b72+Tff7b72= Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4;
Tb4b4b4}
Te6edf3SerialTb4b4b4.Te6edf3printlnTb4b4b4(Te6edf3full_dirTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3stdTff7b72:Tff7b72:Te6edf3string Td2a8ffpreTb4b4b4(Te6edf3prefixTb4b4b4)Tb4b4b4;
Tff7b72preTb4b4b4.Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ff Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Te6edf3File Te6edf3root Tff7b72= Te6edf3FSTb4b4b4.Te6edf3openTb4b4b4(Te6edf3dirTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3rootTb4b4b4) Tb4b4b4{
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Tff7b72preTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printlnTb4b4b4(Ta5d6ff"Ta5d6ff(failed to open directory)Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Te6edf3File Te6edf3file Tff7b72= Te6edf3rootTb4b4b4.Te6edf3openNextFileTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Tffa657charTff7b72* Te6edf3name Tff7b72= Tb4b4b4(Tffa657charTff7b72*Tb4b4b4)Te6edf3fileTb4b4b4.Te6edf3nameTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3stdTff7b72:Tff7b72:Te6edf3string Td2a8ffrecurse_dirTb4b4b4(Te6edf3full_dirTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4.Te6edf3isDirectoryTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3recurse_dir Tff7b72+Tff7b72= Te6edf3nameTb4b4b4;
Te6edf3listDirTb4b4b4(Te6edf3recurse_dirTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4, Tff7b72preTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72else Tb4b4b4{
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Tff7b72preTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
T8b949e//Serial.print("FILE: ");
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Te6edf3nameTb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Ta5d6ff"Ta5d6ff (Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Te6edf3fileTb4b4b4.Te6edf3sizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printlnTb4b4b4(Ta5d6ff"Ta5d6ff bytes)Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3fileTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3file Tff7b72= Te6edf3rootTb4b4b4.Te6edf3openNextFileTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3rootTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72catch Tb4b4b4(Te6edf3stdTff7b72:Tff7b72:Te6edf3exceptionTff7b72& Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Ta5d6ff"Ta5d6fflistDir Exception: Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printlnTb4b4b4(Te6edf3eTb4b4b4.Te6edf3whatTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tffa657void Te6edf3FileSystemTff7b72:Tff7b72:Te6edf3dumpDirTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3dirTb4b4b4) Tb4b4b4{
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Ta5d6ff"Ta5d6ffDIR: Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3stdTff7b72:Tff7b72:Te6edf3string Td2a8fffull_dirTb4b4b4(Te6edf3dirTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3full_dirTb4b4b4.Te6edf3compareTb4b4b4(Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4) Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3full_dir Tff7b72+Tff7b72= Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4;
Tb4b4b4}
Te6edf3SerialTb4b4b4.Te6edf3printlnTb4b4b4(Te6edf3full_dirTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Te6edf3File Te6edf3root Tff7b72= Te6edf3FSTb4b4b4.Te6edf3openTb4b4b4(Te6edf3dirTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3rootTb4b4b4) Tb4b4b4{
Te6edf3SerialTb4b4b4.Te6edf3printlnTb4b4b4(Ta5d6ff"Ta5d6ff(failed to open directory)Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Te6edf3File Te6edf3file Tff7b72= Te6edf3rootTb4b4b4.Te6edf3openNextFileTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Tffa657charTff7b72* Te6edf3name Tff7b72= Tb4b4b4(Tffa657charTff7b72*Tb4b4b4)Te6edf3fileTb4b4b4.Te6edf3nameTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4.Te6edf3isDirectoryTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3stdTff7b72:Tff7b72:Te6edf3string Td2a8ffrecurse_dirTb4b4b4(Te6edf3full_dirTb4b4b4)Tb4b4b4;
Te6edf3recurse_dir Tff7b72+Tff7b72= Te6edf3nameTb4b4b4;
Te6edf3dumpDirTb4b4b4(Te6edf3recurse_dirTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72else Tb4b4b4{
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Ta5d6ff"Tffea00\nTa5d6ffFILE: Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Te6edf3nameTb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Ta5d6ff"Ta5d6ff (Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Te6edf3fileTb4b4b4.Te6edf3sizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printlnTb4b4b4(Ta5d6ff"Ta5d6ff bytes)Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tffa657char Te6edf3dataTb4b4b4[T79c0ff4096Tb4b4b4]Tb4b4b4;
Tffa657size_t Te6edf3size Tff7b72= Te6edf3fileTb4b4b4.Te6edf3sizeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tffa657size_t Te6edf3read Tff7b72= Te6edf3fileTb4b4b4.Te6edf3readBytesTb4b4b4(Te6edf3dataTb4b4b4, Tb4b4b4(Te6edf3size Tff7b72< Tff7b72sizeofTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4) Tff7b72? Te6edf3size Tff7b72: Tff7b72sizeofTb4b4b4(Te6edf3dataTb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3dataTb4b4b4, Te6edf3readTb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printlnTb4b4b4(Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3fileTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3file Tff7b72= Te6edf3rootTb4b4b4.Te6edf3openNextFileTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3rootTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72catch Tb4b4b4(Te6edf3stdTff7b72:Tff7b72:Te6edf3exceptionTff7b72& Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Ta5d6ff"Ta5d6ffdumpDir Exception: Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printlnTb4b4b4(Te6edf3eTb4b4b4.Te6edf3whatTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tff7b72#Tff7b72endif


T8b949e/*virtua*/ Tffa657bool Te6edf3FileSystemTff7b72:Tff7b72:Te6edf3file_existsTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3file_pathTb4b4b4) Tb4b4b4{
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6fffile_exists: checking for existence of file %sTa5d6ff"Tb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4;
T8b949e/*
File file(FS);
if (file.open(file_path, FILE_O_READ)) {
File file = FS.open(file_path, FILE_READ);
if (file) {
bool is_directory = file.isDirectory();
file.close();
return !is_directory;
}
return false;
*/
Tff7b72return Te6edf3path_existsTb4b4b4(Te6edf3file_pathTb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e/*virtua*/ Tffa657size_t Te6edf3FileSystemTff7b72:Tff7b72:Te6edf3read_fileTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3file_pathTb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3BytesTff7b72& Te6edf3dataTb4b4b4) Tb4b4b4{
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffread_file: reading from file %sTa5d6ff"Tb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4;

T8b949e// Avoid VFS noise: don't attempt to open a file that doesn't exist,
T8b949e// since FS.open(path, FILE_READ) on a missing file triggers a
T8b949e// misleading "does not exist, no permits for creation" error from
T8b949e// the ESP-IDF VFS layer (vfs_api.cpp:105).
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3path_existsTb4b4b4(Te6edf3file_pathTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffread_file: file %s does not exist, skippingTa5d6ff"Tb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4;
Tff7b72return T79c0ff0Tb4b4b4;
Tb4b4b4}

Tffa657size_t Te6edf3read Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72#Tff7b72if FS_TYPE == FS_TYPE_INTERNALFS || FS_TYPE == FS_TYPE_FLASHFS
Te6edf3File Td2a8fffileTb4b4b4(Te6edf3FSTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4.Te6edf3openTb4b4b4(Te6edf3file_pathTb4b4b4, Te6edf3FILE_O_READTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72else
Te6edf3File Te6edf3file Tff7b72= Te6edf3FSTb4b4b4.Te6edf3openTb4b4b4(Te6edf3file_pathTb4b4b4, Te6edf3FILE_READTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72endif
Tffa657size_t Te6edf3size Tff7b72= Te6edf3fileTb4b4b4.Te6edf3sizeTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3read Tff7b72= Te6edf3fileTb4b4b4.Te6edf3readBytesTb4b4b4(Tb4b4b4(Tffa657charTff7b72*Tb4b4b4)Te6edf3dataTb4b4b4.Te6edf3writableTb4b4b4(Te6edf3sizeTb4b4b4)Tb4b4b4, Te6edf3sizeTb4b4b4)Tb4b4b4;
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffread_file: read %u bytes from file %sTa5d6ff"Tb4b4b4, Te6edf3readTb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3read Tff7b72!Tff7b72= Te6edf3sizeTb4b4b4) Tb4b4b4{
Te6edf3ERRORFTb4b4b4(Ta5d6ff"Ta5d6ffread_file: failed to read file %sTa5d6ff"Tb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4;
Te6edf3dataTb4b4b4.Te6edf3resizeTb4b4b4(Te6edf3readTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e//TRACE("read_file: closing input file");
Te6edf3fileTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72else Tb4b4b4{
Te6edf3ERRORFTb4b4b4(Ta5d6ff"Ta5d6ffread_file: failed to open input file %sTa5d6ff"Tb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3readTb4b4b4;
Tb4b4b4}

T8b949e/*virtua*/ Tffa657size_t Te6edf3FileSystemTff7b72:Tff7b72:Te6edf3write_fileTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3file_pathTb4b4b4, Tff7b72const Te6edf3RNSTff7b72:Tff7b72:Te6edf3BytesTff7b72& Te6edf3dataTb4b4b4) Tb4b4b4{
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffwrite_file: writing to file %sTa5d6ff"Tb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4;

T8b949e// Avoid VFS noise: ensure the parent directory exists before
T8b949e// attempting FS.open(FILE_WRITE). On some framework versions
T8b949e// the VFS wrapper may still emit the "does not exist" error
T8b949e// even for write/create modes.
Tff7b72const Tffa657charTff7b72* Te6edf3last_slash Tff7b72= Te6edf3strrchrTb4b4b4(Te6edf3file_pathTb4b4b4, Ta5d6ff'Ta5d6ff/Ta5d6ff'Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3last_slash Tff7b72!Tff7b72= Tffa657nullptr Tff7b72&Tff7b72& Te6edf3last_slash Tff7b72!Tff7b72= Te6edf3file_pathTb4b4b4) Tb4b4b4{
T8b949e// file_path has a parent directory (e.g. "/cache/hash")
Tffa657size_t Te6edf3dir_len Tff7b72= Te6edf3last_slash Tff7b72- Te6edf3file_pathTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3dir_len Tff7b72< T79c0ff128Tb4b4b4) Tb4b4b4{
Tffa657char Te6edf3dir_pathTb4b4b4[T79c0ff128Tb4b4b4]Tb4b4b4;
Te6edf3memcpyTb4b4b4(Te6edf3dir_pathTb4b4b4, Te6edf3file_pathTb4b4b4, Te6edf3dir_lenTb4b4b4)Tb4b4b4;
Te6edf3dir_pathTb4b4b4[Te6edf3dir_lenTb4b4b4] Tff7b72= Ta5d6ff'Ta5d6ff\0Ta5d6ff'Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3path_existsTb4b4b4(Te6edf3dir_pathTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3FSTb4b4b4.Te6edf3mkdirTb4b4b4(Te6edf3dir_pathTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

T8b949e// CBA TODO Replace remove with working truncation
Tff7b72if Tb4b4b4(Te6edf3path_existsTb4b4b4(Te6edf3file_pathTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3FSTb4b4b4.Te6edf3removeTb4b4b4(Te6edf3file_pathTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tffa657size_t Te6edf3wrote Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72#Tff7b72if FS_TYPE == FS_TYPE_INTERNALFS || FS_TYPE == FS_TYPE_FLASHFS
Te6edf3File Td2a8fffileTb4b4b4(Te6edf3FSTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4.Te6edf3openTb4b4b4(Te6edf3file_pathTb4b4b4, Te6edf3FILE_O_WRITETb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72else
Te6edf3File Te6edf3file Tff7b72= Te6edf3FSTb4b4b4.Te6edf3openTb4b4b4(Te6edf3file_pathTb4b4b4, Te6edf3FILE_WRITETb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72endif
T8b949e// Seek to beginning to overwrite
T8b949e//file.seek(0);
T8b949e//file.truncate(0);
Te6edf3wrote Tff7b72= Te6edf3fileTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3dataTb4b4b4.Te6edf3dataTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3dataTb4b4b4.Te6edf3sizeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffwrite_file: wrote %u bytes to file %sTa5d6ff"Tb4b4b4, Te6edf3wroteTb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3wrote Tff7b72< Te6edf3dataTb4b4b4.Te6edf3sizeTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3WARNINGFTb4b4b4(Ta5d6ff"Ta5d6ffwrite_file: not all data was written to file %sTa5d6ff"Tb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e//TRACE("write_file: closing output file");
Te6edf3fileTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72else Tb4b4b4{
Te6edf3ERRORFTb4b4b4(Ta5d6ff"Ta5d6ffwrite_file: failed to open output file %sTa5d6ff"Tb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3wroteTb4b4b4;
Tb4b4b4}

T8b949e/*virtual*/ Te6edf3RNSTff7b72:Tff7b72:Te6edf3FileStream Te6edf3FileSystemTff7b72:Tff7b72:Te6edf3open_fileTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3file_pathTb4b4b4, Te6edf3RNSTff7b72:Tff7b72:Te6edf3FileStreamTff7b72:Tff7b72:Te6edf3MODE Te6edf3file_modeTb4b4b4) Tb4b4b4{
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffopen_file: opening file %sTa5d6ff"Tb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if FS_TYPE == FS_TYPE_INTERNALFS || FS_TYPE == FS_TYPE_FLASHFS
Tffa657int Te6edf3modeTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3file_mode Tff7b72=Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3FileStreamTff7b72:Tff7b72:Te6edf3MODE_READTb4b4b4) Tb4b4b4{
Te6edf3mode Tff7b72= Te6edf3FILE_O_READTb4b4b4;
Tb4b4b4}
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3file_mode Tff7b72=Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3FileStreamTff7b72:Tff7b72:Te6edf3MODE_WRITETb4b4b4) Tb4b4b4{
Te6edf3mode Tff7b72= Te6edf3FILE_O_WRITETb4b4b4;
T8b949e// CBA TODO Replace remove with working truncation
Tff7b72if Tb4b4b4(Te6edf3path_existsTb4b4b4(Te6edf3file_pathTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3FSTb4b4b4.Te6edf3removeTb4b4b4(Te6edf3file_pathTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3file_mode Tff7b72=Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3FileStreamTff7b72:Tff7b72:Te6edf3MODE_APPENDTb4b4b4) Tb4b4b4{
T8b949e// CBA This is the default write mode for nrf52 littlefs
Te6edf3mode Tff7b72= Te6edf3FILE_O_WRITETb4b4b4;
Tb4b4b4}
Tff7b72else Tb4b4b4{
Te6edf3ERRORFTb4b4b4(Ta5d6ff"Ta5d6ffopen_file: unsupported mode %dTa5d6ff"Tb4b4b4, Te6edf3file_modeTb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4{Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3NONETb4b4b4}Tb4b4b4;
Tb4b4b4}
Te6edf3FileTff7b72* Te6edf3file Tff7b72= Tff7b72new Te6edf3FileTb4b4b4(Te6edf3FSTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fileTff7b72-Tff7b72>Te6edf3openTb4b4b4(Te6edf3file_pathTb4b4b4, Te6edf3modeTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3ERRORFTb4b4b4(Ta5d6ff"Ta5d6ffopen_file: failed to open output file %sTa5d6ff"Tb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4{Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3NONETb4b4b4}Tb4b4b4;
Tb4b4b4}
T8b949e// Seek to beginning to overwrite (this is failing on nrf52)
T8b949e//if (file_mode == RNS::FileStream::MODE_WRITE) {
T8b949e// file->seek(0);
T8b949e// file->truncate(0);
T8b949e//}
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffopen_file: successfully opened file %sTa5d6ff"Tb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3RNSTff7b72:Tff7b72:Te6edf3FileStreamTb4b4b4(Tff7b72new Te6edf3FileStreamTb4b4b4(Te6edf3fileTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Tff7b72const Tffa657charTff7b72* Te6edf3modeTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3file_mode Tff7b72=Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3FileStreamTff7b72:Tff7b72:Te6edf3MODE_READTb4b4b4) Tb4b4b4{
Te6edf3mode Tff7b72= Te6edf3FILE_READTb4b4b4;
Tb4b4b4}
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3file_mode Tff7b72=Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3FileStreamTff7b72:Tff7b72:Te6edf3MODE_WRITETb4b4b4) Tb4b4b4{
Te6edf3mode Tff7b72= Te6edf3FILE_WRITETb4b4b4;
Tb4b4b4}
Tff7b72else Tff7b72if Tb4b4b4(Te6edf3file_mode Tff7b72=Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3FileStreamTff7b72:Tff7b72:Te6edf3MODE_APPENDTb4b4b4) Tb4b4b4{
Te6edf3mode Tff7b72= Te6edf3FILE_APPENDTb4b4b4;
Tb4b4b4}
Tff7b72else Tb4b4b4{
Te6edf3ERRORFTb4b4b4(Ta5d6ff"Ta5d6ffopen_file: unsupported mode %dTa5d6ff"Tb4b4b4, Te6edf3file_modeTb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4{Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3NONETb4b4b4}Tb4b4b4;
Tb4b4b4}
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffopen_file: opening file %s in mode %sTa5d6ff"Tb4b4b4, Te6edf3file_pathTb4b4b4, Te6edf3modeTb4b4b4)Tb4b4b4;

T8b949e// Avoid VFS noise: don't attempt to open a file that doesn't exist
T8b949e// in read mode (same issue as read_file).
Tff7b72if Tb4b4b4(Te6edf3file_mode Tff7b72=Tff7b72= Te6edf3RNSTff7b72:Tff7b72:Te6edf3FileStreamTff7b72:Tff7b72:Te6edf3MODE_READ Tff7b72&Tff7b72& Tff7b72!Te6edf3path_existsTb4b4b4(Te6edf3file_pathTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffopen_file: file %s does not exist, skippingTa5d6ff"Tb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4{Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3NONETb4b4b4}Tb4b4b4;
Tb4b4b4}

Te6edf3FileTff7b72* Te6edf3file Tff7b72= Tff7b72new Te6edf3FileTb4b4b4(Te6edf3FSTb4b4b4.Te6edf3openTb4b4b4(Te6edf3file_pathTb4b4b4, Te6edf3modeTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3file Tff7b72=Tff7b72= Tffa657nullptr Tff7b72|Tff7b72| Tff7b72!Tb4b4b4(Tff7b72*Te6edf3fileTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3ERRORFTb4b4b4(Ta5d6ff"Ta5d6ffopen_file: failed to open output file %sTa5d6ff"Tb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4{Te6edf3RNSTff7b72:Tff7b72:Te6edf3TypeTff7b72:Tff7b72:Te6edf3NONETb4b4b4}Tb4b4b4;
Tb4b4b4}
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffopen_file: successfully opened file %sTa5d6ff"Tb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3RNSTff7b72:Tff7b72:Te6edf3FileStreamTb4b4b4(Tff7b72new Te6edf3FileStreamTb4b4b4(Te6edf3fileTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}

T8b949e/*virtua*/ Tffa657bool Te6edf3FileSystemTff7b72:Tff7b72:Te6edf3remove_fileTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3file_pathTb4b4b4) Tb4b4b4{
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffremove_file: removing file %sTa5d6ff"Tb4b4b4, Te6edf3file_pathTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3FSTb4b4b4.Te6edf3removeTb4b4b4(Te6edf3file_pathTb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e/*virtua*/ Tffa657bool Te6edf3FileSystemTff7b72:Tff7b72:Te6edf3rename_fileTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3from_file_pathTb4b4b4, Tff7b72const Tffa657charTff7b72* Te6edf3to_file_pathTb4b4b4) Tb4b4b4{
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffrename_file: renaming file %s to %sTa5d6ff"Tb4b4b4, Te6edf3from_file_pathTb4b4b4, Te6edf3to_file_pathTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3FSTb4b4b4.Te6edf3renameTb4b4b4(Te6edf3from_file_pathTb4b4b4, Te6edf3to_file_pathTb4b4b4)Tb4b4b4;
Tb4b4b4}

T8b949e/*virtua*/ Tffa657bool Te6edf3FileSystemTff7b72:Tff7b72:Te6edf3directory_existsTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3directory_pathTb4b4b4) Tb4b4b4{
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffdirectory_exists: checking for existence of directory %sTa5d6ff"Tb4b4b4, Te6edf3directory_pathTb4b4b4)Tb4b4b4;

T8b949e// Use path_exists() (stat-based) instead of FS.open(dir, FILE_READ) to avoid the
T8b949e// noisy VFS "does not exist, no permits for creation" error on
T8b949e// missing directories (same issue as read_file).
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3path_existsTb4b4b4(Te6edf3directory_pathTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}

Tff7b72#Tff7b72if FS_TYPE == FS_TYPE_INTERNALFS || FS_TYPE == FS_TYPE_FLASHFS
Te6edf3File Te6edf3fileTb4b4b4(Te6edf3FSTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4.Te6edf3openTb4b4b4(Te6edf3directory_pathTb4b4b4, Te6edf3FILE_O_READTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72else
Te6edf3File Te6edf3file Tff7b72= Te6edf3FSTb4b4b4.Te6edf3openTb4b4b4(Te6edf3directory_pathTb4b4b4, Te6edf3FILE_READTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72endif
Tffa657bool Te6edf3is_directory Tff7b72= Te6edf3fileTb4b4b4.Te6edf3isDirectoryTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3fileTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3is_directoryTb4b4b4;
Tb4b4b4}
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}

T8b949e/*virtua*/ Tffa657bool Te6edf3FileSystemTff7b72:Tff7b72:Te6edf3create_directoryTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3directory_pathTb4b4b4) Tb4b4b4{
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffcreate_directory: creating directory %sTa5d6ff"Tb4b4b4, Te6edf3directory_pathTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3FSTb4b4b4.Te6edf3mkdirTb4b4b4(Te6edf3directory_pathTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3ERRORTb4b4b4(Ta5d6ff"Ta5d6ffcreate_directory: failed to create directory Ta5d6ff" Tff7b72+ Te6edf3stdTff7b72:Tff7b72:Te6edf3stringTb4b4b4(Te6edf3directory_pathTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}
Tff7b72return Tffa657trueTb4b4b4;
Tb4b4b4}

T8b949e/*virtua*/ Tffa657bool Te6edf3FileSystemTff7b72:Tff7b72:Te6edf3remove_directoryTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3directory_pathTb4b4b4) Tb4b4b4{
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6ffremove_directory: removing directory %sTa5d6ff"Tb4b4b4, Te6edf3directory_pathTb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72if FS_TYPE == FS_TYPE_INTERNALFS || FS_TYPE == FS_TYPE_FLASHFS
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3FSTb4b4b4.Te6edf3rmdir_rTb4b4b4(Te6edf3directory_pathTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72else
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3FSTb4b4b4.Te6edf3rmdirTb4b4b4(Te6edf3directory_pathTb4b4b4)Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72endif
Te6edf3ERRORTb4b4b4(Ta5d6ff"Ta5d6ffremove_directory: failed to remove directory Ta5d6ff" Tff7b72+ Te6edf3stdTff7b72:Tff7b72:Te6edf3stringTb4b4b4(Te6edf3directory_pathTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}
Tff7b72return Tffa657trueTb4b4b4;
Tb4b4b4}

T8b949e/*virtua*/ Te6edf3stdTff7b72:Tff7b72:Te6edf3listTff7b72<Te6edf3stdTff7b72:Tff7b72:Te6edf3stringTff7b72> Te6edf3FileSystemTff7b72:Tff7b72:Te6edf3list_directoryTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3directory_pathTb4b4b4) Tb4b4b4{
Te6edf3TRACEFTb4b4b4(Ta5d6ff"Ta5d6fflist_directory: listing directory %sTa5d6ff"Tb4b4b4, Te6edf3directory_pathTb4b4b4)Tb4b4b4;
Te6edf3stdTff7b72:Tff7b72:Te6edf3listTff7b72<Te6edf3stdTff7b72:Tff7b72:Te6edf3stringTff7b72> Te6edf3filesTb4b4b4;
Te6edf3File Te6edf3root Tff7b72= Te6edf3FSTb4b4b4.Te6edf3openTb4b4b4(Te6edf3directory_pathTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3rootTb4b4b4) Tb4b4b4{
Te6edf3ERRORTb4b4b4(Ta5d6ff"Ta5d6fflist_directory: failed to open directory Ta5d6ff" Tff7b72+ Te6edf3stdTff7b72:Tff7b72:Te6edf3stringTb4b4b4(Te6edf3directory_pathTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3filesTb4b4b4;
Tb4b4b4}
Te6edf3File Te6edf3file Tff7b72= Te6edf3rootTb4b4b4.Te6edf3openNextFileTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72while Tb4b4b4(Te6edf3fileTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3fileTb4b4b4.Te6edf3isDirectoryTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Tffa657charTff7b72* Te6edf3name Tff7b72= Tb4b4b4(Tffa657charTff7b72*Tb4b4b4)Te6edf3fileTb4b4b4.Te6edf3nameTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3filesTb4b4b4.Te6edf3push_backTb4b4b4(Te6edf3nameTb4b4b4)Tb4b4b4;
Tb4b4b4}
T8b949e// CBA Following close required to avoid leaking memory
Te6edf3fileTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3file Tff7b72= Te6edf3rootTb4b4b4.Te6edf3openNextFileTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3rootTb4b4b4.Te6edf3closeTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3TRACETb4b4b4(Ta5d6ff"Ta5d6fflist_directory: returning directory listingTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3filesTb4b4b4;
Tb4b4b4}

T8b949e/*virtual*/ Tffa657size_t Te6edf3FileSystemTff7b72:Tff7b72:Te6edf3storage_sizeTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if FS_TYPE == FS_TYPE_INTERNALFS
Tff7b72return Te6edf3totalBytesTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Tff7b72return Te6edf3FSTb4b4b4.Te6edf3totalBytesTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}

T8b949e/*virtual*/ Tffa657size_t Te6edf3FileSystemTff7b72:Tff7b72:Te6edf3storage_availableTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72if FS_TYPE == FS_TYPE_INTERNALFS
Tff7b72return Tb4b4b4(Te6edf3totalBytesTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3usedBytesTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72else
Tff7b72return Tb4b4b4(Te6edf3FSTb4b4b4.Te6edf3totalBytesTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3FSTb4b4b4.Te6edf3usedBytesTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}

Tff7b72#Tff7b72endif

Served by rngit 1.4.2 - Generated in 0.06s